﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Text;
using System.Threading.Tasks;

namespace Dotnet.Code
{
    public class Cache : ICache
    {
        private static MemoryCache cache = MemoryCache.Default;
        private static Dictionary<string, object> cacheItemsDict = new Dictionary<string, object>();
        private CacheItemPolicy _policy = null;
        private CacheRemoveEventHandler _cacheRemove=null;
        
        public Cache()
        {
            _policy = new CacheItemPolicy();
            _policy.RemovedCallback = OnCacheEntryRemovedCallback;
        }
        #region 事件处理
        public event CacheRemoveEventHandler CacheRemove
        {
            add
            {
                _cacheRemove += value;
            }
            remove
            {
                _cacheRemove -= value;
            }
        }

        protected virtual void OnCacheRemove(CacheRemoveEventArgs e)
        {
            CacheRemoveEventHandler temp = System.Threading.Volatile.Read(ref _cacheRemove);
            if (temp != null)
            {
                temp(this, e);
            }
        }

        private void OnCacheEntryRemovedCallback(CacheEntryRemovedArguments arguments)
        {
            OnCacheRemove(new CacheRemoveEventArgs()
            {
                CacheKey = arguments.CacheItem.Key,
                CacheValue = arguments.CacheItem.Value
            }); 
            //DateTime dt = DateTime.Parse(arguments.CacheItem.Value.ToString());
            //Console.WriteLine("key:{0} value:{1} reason:{2} 移除时间:{3} Timespan:{4}", arguments.CacheItem.Key,
            //    arguments.CacheItem.Value, arguments.RemovedReason.ToString(), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"),
            //    DateTime.Now.Subtract(dt).TotalSeconds);
        }
        //private void OnCacheEntryUpdateCallback(CacheEntryUpdateArguments arguments)
        //{

        //}
        #endregion 
        #region 添加缓存 2021-06-10 16:51:04
        public bool AddCache<T>(T value, string cacheKey) where T : class
        {
            CacheItem item = new CacheItem(cacheKey);
            item.Value = value;
            return cache.Add(item, null);
        }
        public bool AddCache<T>(T value, string cacheKey, int expireTime) where T : class
        {
            throw new NotImplementedException();
        }
        public bool AddCache<T>(T value, string cacheKey, TimeSpan span) where T : class
        {
            CacheItem item = new CacheItem(cacheKey);
            item.Value = value;
            var policy = new CacheItemPolicy()
            {
                AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(span.TotalSeconds),
                RemovedCallback = OnCacheEntryRemovedCallback
            };
            return cache.Add(item, policy);
        }
        #endregion
        #region 读取缓存
        public T GetCache<T>(string cacheKey) where T : class
        {
            if (cache[cacheKey] != null)
            {
                return (T)cache[cacheKey];
            }
            return default(T);
        }
        public T GetCache<T>(string cacheKey, string regionName) where T : class
        {
            cacheKey = regionName + ":" + cacheKey;
            return GetCache<T>(cacheKey);
        }
        #endregion
        #region 写入缓存
        /// <summary>
        /// 写入缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value">缓存值</param>
        /// <param name="cacheKey">缓存键</param>
        public void WriteCache<T>(T value, string cacheKey) where T : class
        {
            CacheItem item = new CacheItem(cacheKey);
            item.Value = value;
            //cache.Add(item, null);
            cache.Set(item, null); //缓存已存在则覆盖
        }


        public void WriteCache<T>(T value, string cacheKey, string regionName) where T : class
        {
            cacheKey = regionName + ":" + cacheKey;
            WriteCache<T>(value, cacheKey);
        }

        public void WriteCache<T>(T value, string cacheKey, int expireTime) where T : class
        {
            CacheItem item = new CacheItem(cacheKey);
            item.Value = value;
            _policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(expireTime);
            _policy.RemovedCallback = OnCacheEntryRemovedCallback;
            cache.Set(item, _policy);
        }


        public void WriteCache<T>(T value, string cacheKey, string regionName, int expireTime) where T : class
        {
            cacheKey = regionName + ":" + cacheKey;
            CacheItem item = new CacheItem(cacheKey);
            item.Value = value;
            _policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(expireTime);
            cache.Add(item, _policy);
        }




        #endregion
        #region 清理缓存
        public void RemoveCache(string cacheKey)
        {
            cache.Remove(cacheKey);
            cacheItemsDict.Remove(cacheKey);
        }
        public void RemoveCache()
        {
            foreach (KeyValuePair<string,
                object> kvp in cacheItemsDict)
            {
                cache.Remove(kvp.Key);
            }
            cacheItemsDict.Clear();
        }
        #endregion

    }
}
